#include "Window.h"


Window::Window(std::wstring title,unsigned int width, unsigned int height):
	m_Title(title),
	m_Active(false),
	m_Width(width),
	m_Height(height),
	m_hDC(NULL),
	m_hInstance(NULL),
	m_hRC(NULL),
	m_hWnd(NULL),
	m_Visible(false),
	m_Created(false)
{
}


Window::~Window(void)
{
}

void Window::SetVisible(bool visible){
	// change of visibility
	if ( visible && !m_Visible )
	{
		if ( !m_Created )
			m_Created = Create();
		ShowWindow(m_hWnd,SW_SHOW);		
	}else if ( !visible && m_Visible) {
		if ( m_Created )
			ShowWindow(m_hWnd,SW_HIDE);
	}
	m_Visible = visible;
}

LRESULT CALLBACK Window::WndProc( HWND	hWnd, UINT	uMsg, WPARAM	wParam,	LPARAM	lParam)
{
	Window* window = (Window*)GetWindowLongPtr(hWnd,GWLP_USERDATA);
	switch (uMsg)									// Check For Windows Messages
	{
		case WM_NCCREATE:
		{ 
			// retrieve Window instance from window creation data and associate
			LPCREATESTRUCT cs = (LPCREATESTRUCT)lParam;
			window = reinterpret_cast<Window *>(cs->lpCreateParams); 
			::SetWindowLongPtr(hWnd, GWL_USERDATA, reinterpret_cast<long>(window)); 

			// save window handle 
			window->SetHWND(hWnd); 
			break;
		} 
		case WM_ACTIVATE:							
		{
			if (!HIWORD(wParam))					
				window->SetActive(true);						
			else
				window->SetActive(false);
			return 0;								
		}

		case WM_SYSCOMMAND:							
		{
			switch (wParam)							
			{
				case SC_SCREENSAVE:					
				case SC_MONITORPOWER:				
				return 0;							
			}
			break;									
		}

		case WM_CLOSE:								
		{
			PostQuitMessage(0);						
			return 0;								
		}

		case WM_KEYDOWN:							
		{
			window->KeyPressed(wParam);
			return 0;								
		}

		case WM_KEYUP:								
		{
			window->KeyReleased(wParam);		
			return 0;								
		}

		case WM_CHAR:
		{
			window->KeyTyped((wchar_t)wParam);
			return 0;
		}

		case WM_SIZE:								
		{
			window->Resize(LOWORD(lParam),HIWORD(lParam)); 
			return 0;								
		}

		case WM_PAINT:
		{
			window->Repaint();
			return 0;
		}
	}
	return DefWindowProc(hWnd,uMsg,wParam,lParam);
}

bool Window::Create()
{
	WNDCLASSEX wc;						
					
	if ( !CreateDefaultWindowClass( wc ) )
		return false;

	DWORD dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;			
	DWORD dwStyle=WS_OVERLAPPEDWINDOW;							
	
	if ( !CreateStyledWindow( dwExStyle, dwStyle) )
		return false;
	
	ShowWindow(m_hWnd,SW_SHOW);						
	SetForegroundWindow(m_hWnd);						
	SetFocus(m_hWnd);									
	Resize(m_Width,m_Height);
	return true;								
}

bool Window::CreateDefaultWindowClass(WNDCLASSEX& wc)
{
	m_hInstance			= GetModuleHandle(NULL);	

	wc.cbSize			= sizeof(WNDCLASSEX);
	wc.style			= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;	
	wc.lpfnWndProc		= (WNDPROC) Window::WndProc;			
	wc.cbClsExtra		= 0;									
	wc.cbWndExtra		= 0;		
	wc.style			= CS_CLASSDC;
	wc.hInstance		= m_hInstance;							
	wc.hIcon			= LoadIcon(NULL, IDI_WINLOGO);			
	wc.hCursor			= LoadCursor(NULL, IDC_ARROW);	
	wc.hIconSm			= LoadIcon(NULL, IDI_WINLOGO);
	wc.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);				
	wc.lpszMenuName		= NULL;									
	wc.lpszClassName	= L"Window";	
	

	if (!RegisterClassExW(&wc))									
	{
		MessageBox(NULL,L"Failed To Register The Window Class.",L"ERROR",MB_OK|MB_ICONEXCLAMATION);
		return false;											
	}else
		return true;
}

bool Window::CreateStyledWindow(DWORD dwExStyle,DWORD	dwStyle)
{
	RECT		WindowRect;				
	WindowRect.left=(long)0;			
	WindowRect.right=(long)m_Width;		
	WindowRect.top=(long)0;				
	WindowRect.bottom=(long)m_Height;	
	AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);		// Adjust Window To True Requested Size

	// Create The Window
	if (!(m_hWnd=CreateWindowEx(	dwExStyle,							
								L"Window",							
								m_Title.c_str(),					
								dwStyle | WS_CLIPSIBLINGS |	WS_CLIPCHILDREN,
								0, 0,								
								WindowRect.right-WindowRect.left,	
								WindowRect.bottom-WindowRect.top,	
								NULL,								
								NULL,								
								m_hInstance,							
								this)))							
	{
		MessageBox(NULL,L"Window Creation Error.",L"ERROR",MB_OK|MB_ICONEXCLAMATION);
		return false;								
	}
	return true;
}
